macOS 平台配置 GitHub Actions(需要非常细心)
概述
本节介绍如何在 GitHub Actions 中为 Electron 应用配置 macOS 和 Linux 平台的自动化打包。macOS 平台涉及代码签名(Code Signing)和公证(Notarization),配置过程繁琐且需要非常细心。核心步骤包括:安装 notarize 工具、修改 electron-builder 配置、申请并导出证书。
配置流程总览
┌─────────────────────────────────────────────────┐
│ Step 1: 安装 electron-builder-notarize │
│ Step 2: 修改 electron-builder 配置 │
│ Step 3: 申请证书 & 导出 base64 编码 │
│ Step 4: 配置 GitHub Secrets │
│ Step 5: 编写 GitHub Actions Workflow │
└─────────────────────────────────────────────────┘
text
Step 1:安装 electron-builder-notarize
npm install -D electron-builder-notarize
# 或
pnpm add -D electron-builder-notarize
bash
Step 2:修改 electron-builder 配置
关闭原有 afterSign
// electron-builder.config.js 或 package.json 中的 build 配置
module.exports = {
appId: 'com.example.myapp',
// ...
mac: {
target: 'dmg',
hardenedRuntime: true,
gatekeeperAssess: false,
// 关闭原有的 afterSign(如果之前有自定义签名脚本)
// afterSign: './build/notarize.js', // 注释掉或删除
},
// 使用 electron-builder-notarize 插件
afterSign: 'electron-builder-notarize',
}
javascript
macOS 完整配置
// electron-builder.config.js
module.exports = {
appId: 'com.example.myapp',
productName: 'MyApp',
directories: {
output: 'dist',
buildResources: 'build',
},
mac: {
category: 'public.app-category.productivity',
target: [
{ target: 'dmg', arch: ['arm64', 'x64'] },
{ target: 'zip', arch: ['arm64', 'x64'] },
],
identity: 'Developer ID Application: Your Name (TEAM_ID)',
icon: 'build/icon.icns',
entitlements: 'build/entitlements.mac.plist',
entitlementsInherit: 'build/entitlements.mac.inherit.plist',
hardenedRuntime: true,
gatekeeperAssess: false,
darkModeSupport: true,
},
dmg: {
title: '${productName} ${version}',
contents: [
{ x: 130, y: 220 },
{ x: 410, y: 220, type: 'link', path: '/Applications' },
],
},
afterSign: 'electron-builder-notarize',
}
javascript
entitlements.mac.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
xml
Step 3:证书申请与导出
证书类型
| 证书 | 用途 | 获取方式 |
|---|---|---|
| Developer ID Application | 签名分发给非 App Store 的应用 | Apple Developer 会员 |
| Developer ID Installer | 签名安装包(PKG) | Apple Developer 会员 |
| Apple Distribution | App Store 分发 | Apple Developer 会员 |
导出证书为 base64
在 macOS 的「钥匙串访问」中导出 .p12 证书文件,然后转换为 base64:
# 导出 p12 为 base64(用于 GitHub Secrets)
base64 -i certificate.p12 | pbcopy
# 验证导出内容
echo "$CSC_LINK_BASE64" | base64 --decode > verify.p12
bash
Step 4:配置 GitHub Secrets
在 GitHub 仓库的 Settings > Secrets and variables > Actions 中配置以下环境变量:
代码签名相关
| Secret 名称 | 值 | 说明 |
|---|---|---|
CSC_LINK | base64 编码的 .p12 证书 | 代码签名证书 |
CSC_KEY_PASSWORD | 证书密码 | 导出 p12 时设置的密码 |
公证(Notarization)相关
| Secret 名称 | 值 | 说明 |
|---|---|---|
APPLE_ID | Apple ID 邮箱 | 开发者 Apple ID |
APPLE_ID_PASSWORD | App-specific password | 在 appleid.apple.com 生成的专用密码 |
APPLE_TEAM_ID | Team ID | 开发者团队标识 |
Step 5:GitHub Actions Workflow
# .github/workflows/build.yml
name: Build Electron App
on:
push:
tags:
- 'v*'
jobs:
build:
strategy:
matrix:
include:
- os: macos-latest
platform: mac
- os: ubuntu-latest
platform: linux
- os: windows-latest
platform: win
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build application
run: pnpm build
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-build
path: dist/*
yaml
环境变量速查
| 环境变量 | 平台 | 说明 |
|---|---|---|
CSC_LINK | macOS / Windows | base64 编码的签名证书 |
CSC_KEY_PASSWORD | macOS / Windows | 证书密码 |
APPLE_ID | macOS | Apple 开发者账号邮箱 |
APPLE_ID_PASSWORD | macOS | App 专用密码 |
APPLE_TEAM_ID | macOS | 开发者团队 ID |
CSC_NAME | macOS | 证书名称(本地开发用) |
常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 签名失败 "no identity found" | 证书未正确导入 CI 环境 | 检查 CSC_LINK 是否完整 base64 编码 |
| 公证超时 | Apple 公证服务响应慢 | 增加超时时间(通常需要 5-10 分钟) |
| dmg 无法打开 | 未启用 hardenedRuntime | 配置 hardenedRuntime: true |
| notarize 失败 | APPLE_ID_PASSWORD 不是 app-specific password | 在 appleid.apple.com 生成专用密码 |
实践要点
- macOS 打包配置需要细心处理证书、签名、公证三个环节
- 使用
electron-builder-notarize简化公证流程,替代自定义 afterSign 脚本 - 所有敏感信息通过 GitHub Secrets 存储,禁止硬编码在代码中
- 证书导出为 base64 编码后存入
CSC_LINK,CI 环境会自动解码使用 - macOS 构建需要
hardenedRuntime: true和正确的 entitlements 配置
↑